package com.ipan.kits.net;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import org.apache.commons.lang3.StringUtils;

import com.ipan.kits.base.ExceptionUtil;
import com.ipan.kits.io.FileUtil;

/**
 * 与URL相关的工具类
 *
 * @author iPan
 * @date 2019-05-25
 */
public class UrlUtil {
	
	/**
	 * 针对ClassPath路径的伪协议前缀（兼容Spring）: "classpath:"
	 */
	public static final String CLASSPATH_URL_PREFIX = "classpath:";
	/**
	 * URL 前缀表示文件: "file:"
	 */
	public static final String FILE_URL_PREFIX = "file:";
	/**
	 * URL 前缀表示jar: "jar:"
	 */
	public static final String JAR_URL_PREFIX = "jar:";
	/**
	 * URL 前缀表示war: "war:"
	 */
	public static final String WAR_URL_PREFIX = "war:";
	/**
	 * URL 协议表示文件: "file"
	 */
	public static final String URL_PROTOCOL_FILE = "file";
	/**
	 * URL 协议表示Jar文件: "jar"
	 */
	public static final String URL_PROTOCOL_JAR = "jar";
	/**
	 * URL 协议表示zip文件: "zip"
	 */
	public static final String URL_PROTOCOL_ZIP = "zip";
	/**
	 * URL 协议表示WebSphere文件: "wsjar"
	 */
	public static final String URL_PROTOCOL_WSJAR = "wsjar";
	/**
	 * URL 协议表示JBoss zip文件: "vfszip"
	 */
	public static final String URL_PROTOCOL_VFSZIP = "vfszip";
	/**
	 * URL 协议表示JBoss文件: "vfsfile"
	 */
	public static final String URL_PROTOCOL_VFSFILE = "vfsfile";
	/**
	 * URL 协议表示JBoss VFS资源: "vfs"
	 */
	public static final String URL_PROTOCOL_VFS = "vfs";
	/**
	 * Jar路径以及内部文件路径的分界符: "!/"
	 */
	public static final String JAR_URL_SEPARATOR = "!/";
	/**
	 * WAR路径及内部文件路径分界符
	 */
	public static final String WAR_URL_SEPARATOR = "*/";
	
	/**
	 * 转URL为URI
	 *
	 * @param url URL
	 * @return URI
	 * @throws UtilException 包装URISyntaxException
	 */
	public static URI toURI(URL url) {
		return toURI(url, false);
	}

	/**
	 * 转URL为URI
	 *
	 * @param url      URL
	 * @param isEncode 是否编码参数中的特殊字符（默认UTF-8编码）
	 * @return URI
	 * @throws UtilException 包装URISyntaxException
	 * @since 4.6.9
	 */
	public static URI toURI(URL url, boolean isEncode) {
		if (null == url) {
			return null;
		}

		return toURI(url.toString(), isEncode);
	}

	/**
	 * 转字符串为URI
	 *
	 * @param location 字符串路径
	 * @return URI
	 * @throws UtilException 包装URISyntaxException
	 */
	public static URI toURI(String location) {
		return toURI(location, false);
	}

	/**
	 * 转字符串为URI
	 *
	 * @param location 字符串路径
	 * @param isEncode 是否编码参数中的特殊字符（默认UTF-8编码）
	 * @return URI
	 * @throws UtilException 包装URISyntaxException
	 * @since 4.6.9
	 */
	public static URI toURI(String location, boolean isEncode) {
		if (isEncode) {
			location = encode(location);
		}
		try {
			return new URI(StringUtils.trim(location));
		} catch (URISyntaxException e) {
			throw ExceptionUtil.wrapRuntime(e);
		}
	}

	/**
	 * 提供的URL是否为文件<br>
	 * 文件协议包括"file", "vfsfile" 或 "vfs".
	 *
	 * @param url {@link URL}
	 * @return 是否为文件
	 * @since 3.0.9
	 */
	public static boolean isFileURL(URL url) {
		String protocol = url.getProtocol();
		return (URL_PROTOCOL_FILE.equals(protocol) || //
				URL_PROTOCOL_VFSFILE.equals(protocol) || //
				URL_PROTOCOL_VFS.equals(protocol));
	}

	/**
	 * 提供的URL是否为jar包URL 协议包括： "jar", "zip", "vfszip" 或 "wsjar".
	 *
	 * @param url {@link URL}
	 * @return 是否为jar包URL
	 */
	public static boolean isJarURL(URL url) {
		final String protocol = url.getProtocol();
		return (URL_PROTOCOL_JAR.equals(protocol) || //
				URL_PROTOCOL_ZIP.equals(protocol) || //
				URL_PROTOCOL_VFSZIP.equals(protocol) || //
				URL_PROTOCOL_WSJAR.equals(protocol));
	}

	/**
	 * 提供的URL是否为Jar文件URL 判断依据为file协议且扩展名为.jar
	 *
	 * @param url the URL to check
	 * @return whether the URL has been identified as a JAR file URL
	 * @since 4.1
	 */
	public static boolean isJarFileURL(URL url) {
		return (URL_PROTOCOL_FILE.equals(url.getProtocol()) && //
				url.getPath().toLowerCase().endsWith(FileUtil.EXT_JAR));
	}

    /**
     * url编码，字符集采用{@code UTF-8}
     *
     * @param url 待编码的url
     * @return 编码后的url
     */
    public static String encode(final String url) {
        return encode(url, StandardCharsets.UTF_8);
    }

    /**
     * url编码，指定字符集
     *
     * @param url     待编码的url
     * @param charset 指定字符集
     * @return 编码后的url
     */
    public static String encode(final String url, Charset charset) {
        if (StringUtils.isEmpty(url)) {
            return StringUtils.EMPTY;
        }
        if (charset == null) {
            charset = StandardCharsets.UTF_8;
        }
        try {
            return URLEncoder.encode(url, charset.name());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 为url增加请求参数
     *
     * @param url      原始的请求地址
     * @param name     参数名
     * @param value    参数值
     * @param encoding 编码
     * @return 返回追加了参数的地址
     */
    public static String addParameters(String url, String name, String value, String encoding) {
        if (StringUtils.isEmpty(url)) {
            return StringUtils.EMPTY;
        }
        if (StringUtils.isEmpty(name) || StringUtils.isEmpty(value)) {
            return url;
        }
//        if (encoding == null) {
//            encoding = StandardCharsets.UTF_8.name();
//        }
        try {
            String queryString = name + "=" + ((StringUtils.isNotBlank(encoding)) ? URLEncoder.encode(value, encoding) : value);
            if (url.contains("?")) {
                return url + "&" + queryString;
            } else {
                return url + "?" + queryString;
            }
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 为url增加请求参数
     *
     * @param url      原始的请求地址
     * @param name     参数名
     * @param value    参数值
     * @param encoding 编码
     * @return 返回追加了参数的地址
     */
    public static String addParameters(String url, String name, String value) {
        return addParameters(url, name, value, null);
    }

    /**
     * URL解码，字符集采用{@code UTF-8}
     *
     * @param url 待解码的url
     * @return 解码后的url
     */
    public static String decode(final String url) {
        return decode(url, StandardCharsets.UTF_8);
    }

    /**
     * URL解码，指定字符集
     *
     * @param url     待解码的url
     * @param charset 指定字符集
     * @return 解码后的url
     */
    public static String decode(final String url, Charset charset) {
        if (StringUtils.isEmpty(url)) {
            return StringUtils.EMPTY;
        }
        if (charset == null) {
            charset = StandardCharsets.UTF_8;
        }
        try {
            return URLDecoder.decode(url, charset.name());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

}
